<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <link rel="icon" type="image/svg+xml" href="/vite.svg"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>select-rect</title>
</head>
<body>
<div id="container"></div>
<script type="module">
    import Konva from "konva";

    let CONTEXT_MENU_ID = 'contextmenu';
    var width = window.innerWidth;
    var height = window.innerHeight;

    let stage = new Konva.Stage({container: 'container', width: width, height: height});
    let layer = new Konva.Layer();
    stage.add(layer);

    let rect1 = new Konva.Rect({x: 60, y: 60, width: 100, height: 90, fill: 'red', name: 'rect', draggable: true});
    let rect2 = new Konva.Rect({x: 250, y: 100, width: 150, height: 90, fill: 'blue', name: 'rect', draggable: true});
    layer.add(rect1);
    layer.add(rect2);

    rect1.on('dblclick', (e) => {
        e.target.setAttrs({
            fill: 'lightblue'
        })
    })

    rect1.on('contextmenu', (e) => {
        e.evt.preventDefault();

        let pointerPosition = stage.getPointerPosition();
        let x = pointerPosition.x;
        let y = pointerPosition.y;

        let div = document.getElementById(CONTEXT_MENU_ID);
        if (!div) {
            div = document.createElement("div");
            div.id = CONTEXT_MENU_ID;
            document.body.appendChild(div);
            div.style.width = "100px";
            div.style.height = "500px";
            div.style.backgroundColor = 'pink';
            div.style.position = "fixed";
            div.innerText = "右键菜单";
        }
        div.style.left = x + 'px';
        div.style.top = y + 'px';
    })

    let tr = new Konva.Transformer();
    layer.add(tr);
    tr.nodes([rect1, rect2]);

    let selectionRectangle = new Konva.Rect({fill: 'rgb(0, 0, 255, 0.5)', visible: false, listening: false});
    layer.add(selectionRectangle);

    var x1, y1, x2, y2;
    var selecting = false;
    stage.on('mousedown touchstart', (e) => {
        // 如果没有没有点击任何形状，不做任何事情
        if (e.target !== stage) {
            return;
        }

        e.evt.preventDefault();
        let pointerPosition = stage.getPointerPosition();
        x1 = pointerPosition.x;
        y1 = pointerPosition.y;
        x2 = x1;
        y2 = y1;

        selectionRectangle.width(0);
        selectionRectangle.height(0);
        selecting = true;
    });

    stage.on('mousedown', (e) => {
        let contextMenu = document.getElementById(CONTEXT_MENU_ID);
        if (contextMenu) {
            contextMenu.remove();
        }
    })

    stage.on('mouseup touchend', (e) => {
        selecting = false;

        if (!selectionRectangle.visible()) {
            return;
        }

        e.evt.preventDefault();
        selectionRectangle.visible(false);
        let shapes = stage.find('.rect');
        let box = selectionRectangle.getClientRect();
        // 判断图形是否有交叉(haveIntersection)
        let selected = shapes.filter((shape) => Konva.Util.haveIntersection(box, shape.getClientRect()));
        tr.nodes(selected);
    });

    stage.on('click tap', (e) => {
        if (selectionRectangle.visible()) {
            return;
        }

        if (e.target === stage) {
            tr.nodes([]);
            return;
        }

        if (!e.target.hasName('rect')) {
            return;
        }

        const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
        const isSelected = tr.nodes().indexOf(e.target) >= 0;

        if (!metaPressed && !isSelected) {
            tr.nodes([e.target]);
        } else if (metaPressed && isSelected) {
            let nodes = tr.nodes().slice();
            nodes.splice(nodes.indexOf(e.target), 1);
            tr.nodes(nodes);
        } else if (metaPressed && !isSelected) {
            let nodes = tr.nodes().concat([e.target]);
            tr.nodes(nodes);
        }
    });

    stage.on('mousemove touchmove', (e) => {
        if (!selecting) {
            return;
        }

        let pointerPosition = stage.getPointerPosition();
        x2 = pointerPosition.x;
        y2 = pointerPosition.y;

        selectionRectangle.setAttrs({
            visible: true,
            x: Math.min(x1, x2),
            y: Math.min(y1, y2),
            width: Math.abs(x1 - x2),
            height: Math.abs(y1 - y2)
        });
    });
</script>
</body>
</html>
